package de.LooLo;

import java.io.IOException;
import java.util.ArrayList;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import android.util.Log;

/**
 * LooGetter gets the loos from Openstreetmap.org in the current region.
 * Also holds a Cached List of current loos available
 * @author Kevin Seppelt, Lukas Siedel 
 * 
 */
public class LooGetter {

	private int taskTicket = 1;
	private static LooGetter instance;
	private Toilet newLoo = null;
	public boolean isLoo = false;
	public ArrayList<String> tagName = new ArrayList<String>();
	public ArrayList<String> tagValue = new ArrayList<String>();

	private LooGetter() {
	};

	public static LooGetter getInstance() {
		if (instance == null) {
			instance = new LooGetter();
		}
		return instance;
	}

	/**
	 * List of Loos
	 */
	private ArrayList<Toilet> looList = new ArrayList<Toilet>();

	/**
	 * @return List of Loos
	 */
	public ArrayList<Toilet> getLooList() {
		return looList;
	}

	/**
	 * Downloads a list of Toilets from Openstreetmap.org with the following
	 * specifications:
	 * 
	 * @param lon
	 *            longitude of current position
	 * @param lat
	 *            latitude of current position
	 * @param frameSize
	 *            size of region in which toilets are loaded
	 */
	public void getLoos(double lon, double lat, double frameSize) {

		looList.clear();
		double left = 0;
		double bottom = 0;
		double right = 0;
		double top = 0;
		frameSize = frameSize / 2;

		bottom = lat - (Double.parseDouble(String.valueOf(frameSize)) / 111);
		top = lat + (Double.parseDouble(String.valueOf(frameSize)) / 111);
		left = lon - (Double.parseDouble(String.valueOf(frameSize)) / 64);
		right = lon + (Double.parseDouble(String.valueOf(frameSize)) / 64);

		HttpClient httpClient = new DefaultHttpClient();
		HttpHost httpHost = new HttpHost("www.openstreetmap.org");
        
		HttpGet httpGet = new HttpGet(
				"/api/0.6/map?bbox=" + left + ","
						+ bottom + "," + right + "," + top);
		Log.d("HGET", httpGet.getURI() + "");
		HttpResponse response = null;
		try {
			response = httpClient.execute(httpHost,httpGet);
			SAXParserFactory factory = SAXParserFactory.newInstance();
			SAXParser saxParser = factory.newSAXParser();
			ToiletHandler handler = new ToiletHandler();
			saxParser.parse(response.getEntity().getContent(), handler);

		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SAXException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			httpGet.abort();
		}

		Log.d("Notification",
				"Analysation finished! Loos found: " + looList.size());
		
	}

	public int getTicketCount() {
		return taskTicket;
	}

	public void releaseTicket() {
		taskTicket++;
	}

	public void useTaskTicket() {
		taskTicket--;
	}

	public void setLooList(ArrayList<Toilet> list) {
		looList = list;
	}

	class ToiletHandler extends DefaultHandler {
		// private ArrayList<Toilet> looList = new ArrayList<Toilet>();
		private String lastLon = null;
		private String lastLat = null;
		public boolean nodesEnd = false;

		@Override
		public void startElement(String uri, String localName, String qName,
				Attributes attributes) throws SAXException {

			if (nodesEnd) {
				throw new SAXException("End reached");
			} else {
				if (localName.equals("node")) {
					if (isLoo) {
						if (newLoo.insideBuilding)
							setPropertys();
						looList.add(newLoo);
					}
					tagName.clear();
					tagValue.clear();
					isLoo = false;
					lastLon = attributes.getValue("lon");
					lastLat = attributes.getValue("lat");
				} else if (localName.equals("tag")) {
					String k = attributes.getValue("k");
					String v = attributes.getValue("v");

					if (attributes.getValue(1).equals("toilets")) {
						newLoo = new Toilet();
						isLoo = true;
						newLoo.setLongitude(Double.parseDouble(lastLon));
						newLoo.setLatitude(Double.parseDouble(lastLat));
						newLoo.setInsideBuilding(false);
					} else if (isLoo) {
						if (k.equals("charge") || k.equals("fee")) {
							newLoo.setFee(v);
						} else if (k.equals("wheelchair")) {
							newLoo.setWheelchair(v);
						} else if (k.equals("layer")) {
							newLoo.setLayer(v);
						} else if (k.equals("name")) {
							newLoo.setName(v);
						} else if (k.equals("supervised")) {
							newLoo.setSupervised(v);
						} else if (k.equals("opening_hours")) {
							newLoo.setOpening_hours(v);
						}
					} else {
						tagName.add(k);
						tagValue.add(v);
						if (k.equals("toilet") || k.equals("toilets")
								|| k.equals("wheelchair:toilets")
								|| k.equals("wheelchair:toilet")) {
							
							if (v.equals("yes")) {
								newLoo = new Toilet();
								isLoo = true;
								newLoo.setLongitude(Double.parseDouble(lastLon));
								newLoo.setLatitude(Double.parseDouble(lastLat));
								newLoo.setInsideBuilding(true);
								if (k.equals("wheelchair:toilets")
										|| k.equals("wheelchair:toilet")) {
									newLoo.setWheelchair(v);
								}
							}
						}
					}

				} else if (localName.equals("way")) {
					nodesEnd = true;
				}
			}
		}

		private void setPropertys() {
			for (int i = 0; i < tagName.size(); i++) {
				String k = tagName.get(i);
				String v = tagValue.get(i);
				if (k.equals("charge") || k.equals("fee")) {
					newLoo.setFee(v);
				} else if (k.equals("wheelchair")) {
					newLoo.setWheelchair(v);
				} else if (k.equals("layer")) {
					newLoo.setLayer(v);
				} else if (k.equals("name")) {
					newLoo.setName(v);
				} else if (k.equals("supervised")) {
					newLoo.setSupervised(v);
				} else if (k.equals("opening_hours")) {
					newLoo.setOpening_hours(v);
				}

			}
		}
	}

}
